﻿using Core.Enums;
using Core.Interfaces;
using Hangfire;
using Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Infrastructure.Repositories
{
    public class GenericRepository<T> : IGenericRepository<T> where T : class
    {
        private readonly ApplicationDbContext _context;
        private readonly CacheTech cacheTech= CacheTech.Memory;
        private readonly Func<CacheTech,ICacheService> cacheService;
        private readonly string cacheKey=$"{typeof(T).Name}";

        public GenericRepository(ApplicationDbContext context, Func<CacheTech, ICacheService> cacheService)
        {
            _context = context;
            this.cacheService = cacheService;
        }

        public async Task<T> AddAsync(T item)
        {
            await _context.Set<T>().AddAsync(item);
            await _context.SaveChangesAsync();
            BackgroundJob.Enqueue(()=>RefreshCache());
            return item;
        }

        public async Task DeleteAsync(int id)
        {
            var entity=await _context.Set<T>().FindAsync(id);
            if (entity != null) {
                _context.Remove(entity);
                await _context.SaveChangesAsync();
                BackgroundJob.Enqueue(()=>RefreshCache());
            }
        }

        public async Task<IReadOnlyList<T>> GetAllAsync()
        {
            if (!cacheService(cacheTech).TryGet<IReadOnlyList<T>>(cacheKey,out IReadOnlyList<T> cachesValue))
            {

               var cacheValue= await _context.Set<T>().ToListAsync();
                cacheService(cacheTech).Set<IReadOnlyList<T>>(cacheKey, cacheValue);
            }
            return cachesValue;
            
        }

        public async Task<T> GetByIdAsync(int id)
        {
            return await _context.Set<T>().FindAsync(id);
        }

        public async Task<T> UpdateAsync(T item)
        {
            _context.Update(item);
            await _context.SaveChangesAsync();
            BackgroundJob.Enqueue(() => RefreshCache());
            return item;
        }

        public async Task RefreshCache()
        {
            cacheService(cacheTech).Remove<T>(cacheKey);
            var cacheList=await _context.Set<T>().ToListAsync();
            cacheService(cacheTech).Set(cacheKey, cacheList);
        }
    }
}
